﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Workflows.Components.Entities.Documents.Terms
{
    /// <summary>
    /// 
    /// </summary>
    public class TermSimilarityMatrix
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="terms"></param>
        /// <returns></returns>
        public static Dictionary<int, Dictionary<int, double>> BuildTermDistanceMatrixUsingNgram(
            List<Term> terms)
        {
            Dictionary<int, Dictionary<int, double>> termSimilarityMatrix =
                new Dictionary<int, Dictionary<int, double>>();
            for (int i = 0; i < terms.Count; i++)
            {
                string txt1 = terms[i].Phrase;
                Dictionary<int, double> similarities = new Dictionary<int, double>();
                for (int k = 0; k < terms.Count; k++)
                {
                    string txt2 = terms[k].Phrase;
                    similarities.Add(terms[k].TermID, NGramUtil.ComputeNGramSimilarity(txt1, txt2, 4));
                }
                termSimilarityMatrix.Add(terms[i].TermID, similarities);
            }
            return termSimilarityMatrix;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="termFreqs1"></param>
        /// <param name="termFreqs2"></param>
        /// <returns></returns>
        public static Dictionary<int, Dictionary<int, double>> BuildTermDistanceMatrixUsingNgram(
            BagOfWords termFreqs1, BagOfWords termFreqs2)
        {
            List<Term> terms = new List<Term>();
            List<int> unionTermIDs = new List<int>();
            foreach (int termID in termFreqs1.TermFreqs.Keys)
            {
                Term term = new Term(termID, termFreqs1.TermPhrases[termID],termFreqs1.TermWeights[termID]);
                terms.Add(term);
                unionTermIDs.Add(termID);
            }
            foreach (int termID in termFreqs2.TermFreqs.Keys)
            {
                if (!unionTermIDs.Contains(termID))
                {
                    Term term = new Term(termID,termFreqs2.TermPhrases[termID],termFreqs2.TermWeights[termID]);
                    terms.Add(term);
                }
            }

            return TermSimilarityMatrix.BuildTermDistanceMatrixUsingNgram(terms);
        }

        /// <summary>
        /// root word -> list of term ids
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, List<int>> BuildTermInflectionalStemmingMappings(List<Term> terms)
        {
            InflectionalStemmer stemmer = new InflectionalStemmer();
            Dictionary<string, List<int>> termStemmings = new Dictionary<string, List<int>>();
            foreach (Term term in terms)
            {
                string[] words = term.Phrase.Split(new char[] { ' ' });
                foreach (string word in words)
                {
                    string root = stemmer.StemTerm(word).ToLower();
                    if (termStemmings.ContainsKey(root))
                    {
                        List<int> termIDs = termStemmings[root];
                        if (!termIDs.Contains(term.TermID))
                            termIDs.Add(term.TermID);
                        termStemmings[root] = termIDs;
                    }
                    else
                    {
                        List<int> termIDs = new List<int>();
                        termIDs.Add(term.TermID);
                        termStemmings.Add(root, termIDs);
                    }
                }
            }

            return termStemmings;
        }

        /// <summary>
        /// root word -> list of term ids
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, List<int>> BuildTermPorterStemmingMappings(List<Term> terms)
        {
            PorterStemmer stemmer = new PorterStemmer();
            Dictionary<string, List<int>> termStemmings = new Dictionary<string, List<int>>();
            foreach (Term term in terms)
            {
                string[] words = term.Phrase.Split(new char[] { ' ' });
                foreach (string word in words)
                {
                    string root = stemmer.StemTerm(word).ToLower();
                    if (termStemmings.ContainsKey(root))
                    {
                        List<int> termIDs = termStemmings[root];
                        if (!termIDs.Contains(term.TermID))
                            termIDs.Add(term.TermID);
                        termStemmings[root] = termIDs;
                    }
                    else
                    {
                        List<int> termIDs = new List<int>();
                        termIDs.Add(term.TermID);
                        termStemmings.Add(root, termIDs);
                    }
                }
            }

            return termStemmings;
        }

    }
}
